using System;
using System.Collections.Generic;

namespace WbsEditor
{
    public class WbsTraverser
    {
        public static bool ExistsNodeWithPredicate(WbsNode node, Predicate<WbsNode> predicate)
        {
            if (predicate(node))
                return true;

            foreach (WbsNode child in node.ChildNodes)
            {
                if (ExistsNodeWithPredicate(child, predicate))
                    return true;
            }

            return false;
        }

        public static WbsNode FindNodeWithPredicate(WbsNode node, Predicate<WbsNode> predicate)
        {
            if (predicate(node))
                return node;

            foreach (WbsNode child in node.ChildNodes)
            {
                WbsNode returnNode = FindNodeWithPredicate(child, predicate);
                if (null != returnNode)
                    return returnNode;
            }

            return null;
        }
        public delegate void Func<T>(T obj);

        public static void TraverseTree(WbsNode node, WbsEditor.WbsTraverser.Func<WbsNode> func)
        {
            func(node);

            foreach (WbsNode child in node.ChildNodes)
            {
                TraverseTree(child, func);
            }
        }

        public static bool ExistsPublishedNodeInTree(WbsNode node)
        {
            return ExistsNodeWithPredicate(node,
                delegate(WbsNode n)
                {
                    return n.IsPublished;
                });
        }

        public static void GetWorkItemIdsInTree(WbsNode node, List<int> workItemList)
        {
            if (node.IsPublished)
            {
                workItemList.Add(node.WorkItemId);
            }
            foreach (WbsNode child in node.ChildNodes)
            {
                GetWorkItemIdsInTree(child, workItemList);
            }
        }

        public static bool ExistsNodeWithWorkItemIdsInTree(WbsNode node, List<int> workItemList)
        {
            return ExistsNodeWithPredicate(node,
                delegate(WbsNode n)
                {
                    if (!n.IsPublished)
                        return false;
                    return workItemList.Contains(n.WorkItemId);
                });
        }

        public static void ResetWorkItemIdsForList(WbsNode node, List<int> workItemIdList)
        {
            // Trick to traverse the tree: The predicate never returns
            // true, thus the entire tree will be traversed :)
            ExistsNodeWithPredicate(node,
                delegate(WbsNode n)
                {
                    if (!n.IsPublished)
                        return false;
                    if (workItemIdList.Contains(n.WorkItemId))
                    {
                        n.WorkItemId = -1;
                    }
                    return false;
                });
        }

        public static WbsNode GetNodeWithWorkItemId(WbsNode node, int id)
        {
            if (node.WorkItemId == id)
                return node;
            foreach (WbsNode child in node.ChildNodes)
            {
                WbsNode returnNode = GetNodeWithWorkItemId(child, id);
                if (null != returnNode)
                    return returnNode;
            }
            return null;
        }
    }
}